package com.lensyn.generator.plugins;

import com.lensyn.generator.handler.ServiceNameHandler;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.internal.util.JavaBeansUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * Service  生成器
 * @author xiaob@lensysn.com
 * @date 2016/12/20
 * @see CUIDPlugin#generateServiceInterface(IntrospectedTable, TopLevelClass)
 */
public class GenerateServiceInterface {

    protected IntrospectedTable introspectedTable;

    protected TopLevelClass dtoClass;

    protected ServiceNameHandler serviceNameHandler;


    public GenerateServiceInterface(IntrospectedTable introspectedTable, TopLevelClass dtoClass, ServiceNameHandler serviceNameHandler) {
        this.introspectedTable = introspectedTable;
        this.dtoClass = dtoClass;
        this.serviceNameHandler = serviceNameHandler;
    }

    public Interface generate() {
        Interface face = new Interface(serviceNameHandler.serviceName(
                introspectedTable.getFullyQualifiedTable().getIntrospectedTableName()
        ));
        face.setVisibility(JavaVisibility.PUBLIC);
        face.addImportedType(dtoClass.getType());
        face.addImportedType(new FullyQualifiedJavaType("org.springframework.transaction.annotation.Transactional"));
        face.addImportedType(new FullyQualifiedJavaType("java.util.List"));


        face.addAnnotation("@Transactional");


        List<Method> methods = addMethods();
        for (Method method : methods) {
            face.addMethod(method);
        }

        NameUtils.addClassComment(face, introspectedTable, " Service");

        return face;
    }

    private List<Method> addMethods() {
        List<Method> methods = new ArrayList<Method>();
        methods.add(addMethod());
        methods.add(deleteMethod());
        methods.add(updateMethod());
        methods.add(findByIdMethod());


        return methods;
    }

    private String getEntityName(boolean firstUpper) {
        return JavaBeansUtil.getCamelCaseString(introspectedTable.getFullyQualifiedTable().getIntrospectedTableName(), firstUpper);
    }

    private Method addMethod() {
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(dtoClass.getType());
        method.setName("add" + getEntityName(true));

        Parameter dtoParam = new Parameter(dtoClass.getType(),
                JavaBeansUtil.getValidPropertyName(dtoClass.getType().getShortName()));
        method.addParameter(dtoParam);

        NameUtils.addMethodComment(method, "Add");
        return method;
    }

    private Method deleteMethod() {
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(new FullyQualifiedJavaType("int"));
        method.setName("delete" + getEntityName(true));

        Parameter dtoParam = new Parameter(new FullyQualifiedJavaType("java.lang.String"),
                "ids");
        method.addParameter(dtoParam);

        NameUtils.addMethodComment(method, "Delete");
        return method;
    }

    private Method updateMethod() {
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(dtoClass.getType());
        method.setName("update" + getEntityName(true));

        Parameter dtoParam = new Parameter(dtoClass.getType(),
                JavaBeansUtil.getValidPropertyName(dtoClass.getType().getShortName()));

        method.addParameter(dtoParam);

        NameUtils.addMethodComment(method, "Update");
        return method;
    }

    private Method findByIdMethod() {
        Method method = new Method();



        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(listType(dtoClass.getType()));
        method.setName("find" + getEntityName(true));
        Parameter dtoParam = new Parameter(new FullyQualifiedJavaType("java.lang.String"),
                "ids");
        method.addParameter(dtoParam);

        NameUtils.addMethodComment(method, "find");
        return method;
    }


    private FullyQualifiedJavaType listType(FullyQualifiedJavaType type ){
        FullyQualifiedJavaType list = new FullyQualifiedJavaType("java.util.List");
        if(type!=null){
            list.addTypeArgument(type);
        }
        return list;
    }


}
